package graphics.screens.search;

import java.io.IOException;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;

import state.State;
import tool.KeyCode;
import tool.Log;
import boot.Boot;
import db.DBListener;
import db.DBReader;
import db.Mp3DBRecord;
import files.Files;
import function.Mp3File;
import function.search.EventListener;
import function.search.SearchKeyHandler2;
import graphics.Background;
import graphics.BootColor;
import graphics.SearchChoiceInput2;
import graphics.SearchInput2;

public class TitleSearchScreen extends Canvas implements CommandListener,
		EventListener {

	private static final int NUM_KEY = 3;
	private SearchInput2 searchInput;
	private SearchKeyHandler2 searchKeyHandler;
	private DBReader dbReader;
	private SearchChoiceInput2 tuneChoiceInput;
	private String searchInputValue;
	private Mp3File[] mp3List;
	private Background background;
	private Boot boot;
	private final Command cancelCommand = new Command("Cancel", Command.EXIT, 1);

	public TitleSearchScreen() {
		boot = Boot.getInstance();
		addCommand(cancelCommand);
		setCommandListener(this);
		reboot();
	}

	protected void paint(Graphics g) {

		background.repaint(g);

		if (Boot.state().equals(State.TITLE_SEARCH_ENGAGED)) {
			searchInput.repaint(g);
		} else if (Boot.state().equals(State.DISPLAY_TITLES_FROM_SEARCH)) {
			tuneChoiceInput.repaint(g);
		}

	}

	public void commandAction(Command command, Displayable dis) {
		if (command == cancelCommand) {
			reboot();
		}
	}

	public void keyPressed(int keyCode) {

		if (Boot.state().equals(State.DISPLAY_TITLES_FROM_SEARCH)) {
			tuneChoiceInput.keyPressed(keyCode);
			repaint();
		} else if (Boot.state().equals(State.TITLE_SEARCH_ENGAGED)) {
			searchKeyHandler.keyPressed(keyCode);
			repaint();

			if ((keyCode == KeyCode.HAUT) || (keyCode == KeyCode.BAS)) {
				Boot.state().remove(State.TITLE_SEARCH_ENGAGED);
				Boot.state().remove(State.DISPLAY_TITLES_FROM_SEARCH);
				boot.displayRelevantScreen();
			}
		}

	}

	public void reboot() {
		background = new Background();
		searchInput = new SearchInput2(this, NUM_KEY,
				BootColor.BASIC_MENU_COLOR);
		searchKeyHandler = new SearchKeyHandler2(NUM_KEY, searchInput, this);
		searchKeyHandler.addListener(this);
		Boot.state().remove(State.DISPLAY_TITLES_FROM_SEARCH);
		Boot.state().add(State.TITLE_SEARCH_ENGAGED);
	}

	public void processEvent(String event) {
		if (EventListener.EVENT_PROCESS_DONE.equals(event)) {
			searchInputValue = searchKeyHandler.getSearchInput();
			computeDB();
			String[] titleList = getTitleList();
			tuneChoiceInput = new SearchChoiceInput2(titleList);
			tuneChoiceInput.addListener(new TuneChoiceListener());

			Boot.state().remove(State.TITLE_SEARCH_ENGAGED);
			Boot.state().add(State.DISPLAY_TITLES_FROM_SEARCH);
			repaint();
		} else if (EventListener.EVENT_REPAINT_REQUIRED.equals(event)) {
			repaint();
		}
	}

	private String[] getTitleList() {
		String[] result = new String[mp3List.length];
		for (int i = 0; i < mp3List.length; i++) {
			result[i] = mp3List[i].getTitle();
		}
		return result;
	}

	private void computeDB() {

		String dbPath = Files.BOOT_ROOT + "/NoPoubelle.db";

		if (Boot.state().equals(State.WICKED_KEY_PRESSED)) {
			dbPath = Files.BOOT_ROOT + "/Boot.db";
		}

		dbReader = new DBReader(dbPath);
		dbReader.addListener(new DBListener() {

			private int index = 0;
			private Mp3File[] tempList = new Mp3File[200];

			public void processRecord(Mp3DBRecord record) {
				String title = record.getTitle();
				int titleLength = title.length();
				if (titleLength < NUM_KEY) {
					for (int i = 0; i < NUM_KEY - titleLength; i++) {
						title += " ";
					}
				}
				String recordKey = title.substring(0, NUM_KEY).toLowerCase();
				if (searchInputValue.equals(recordKey)) {
					tempList[index] = record.getMp3File();
					index++;
				} else if (recordKey.compareTo(searchInputValue) > 0) {
					try {
						Log.log("Stop searching db at :\n\"" + title + "\"");
						Log.log("Record key =  :\n\"" + recordKey + "\"");
						Log.log("Search input value =  :\n\""
								+ searchInputValue + "\"");
						dbReader.stopReading();
					} catch (IOException e) {
						Boot.alertException(e, this, "computeDB()");
					}
				}
			}

			public void readingDone() {
				mp3List = new Mp3File[index];
				for (int i = 0; i < mp3List.length; i++) {
					mp3List[i] = tempList[i];
				}
			}
		});

		dbReader.readDB();
	}

	private class TuneChoiceListener implements EventListener {

		public void processEvent(String event) {
			int chosenIndex = tuneChoiceInput.getchosenIndex();
			Mp3File chosenMp3 = mp3List[chosenIndex];
			boot.enqueueMp3(chosenMp3);
			boot.readyToGo();
			reboot();
		}

	}
}
